
from olpcgames import pangofont


# allow 70% and disallow 30%
ALLOW_PERCENT = 70


from xml.etree.ElementTree import Element, SubElement, dump, parse, ElementTree, XML
from random import Random

# should be dict instead of list
class Board(list):
    """ Board class
    """

    def __init__(self, width, height):
        """ init base on a required width and height parameter
        """
        #
        # need to try/catch that it's an INT throw exception
        try:
            #""" WIDTH and HEIGHT are the dimensions of the board in squares """
            self.WIDTH  = int(width)
            self.HEIGHT = int(height)
        except ValueError:
            raise ValueError, 'Width and Height must be integers'

        if self.WIDTH <= 0 or self.HEIGHT <= 0:
            raise ValueError, 'Width and Height must be integers > 0'
            # you can create another sub-class of Exception to have a custom error here if
            # such a refinement is necessary TODO TODO TODO

        # create a list fill it with 0's by default
        self.extend(self.WIDTH * self.HEIGHT * [None])

        # create default descriptions
        self.description = 'Default uninitialized board'
        self.level = 0
        self.allowed = []
        self.disallowed = []
        self.max_text_length = 0 # from the allowed/disallowed lists, the max text length usable (used for drawing)

        # cached fonts that will be used to draw
        # only cache of all the current board's available numbers
        self.cached_fonts = None

        # constants (enums)
        self.VALUE_NONE = 0
        self.VALUE_ALLOWED = 1
        self.VALUE_DISALLOWED = 2

    def CreateBoard(self, allowed_percent):
        """ initialize the board given the values in its lists, and a certain percent will be allowed """
        #for loc in self:
        #    print loc

        # TODO TODO TODO: ALLOWED PERCENT MUST BE 0-100 ... and a number at that
        
        # create a list of values we'll populate with in with the values we plan to use
        randlist = len(self) * [None]
        #print randlist
        for i in range(0, len(self), 1):
            # NEED 100.0 or else you get major problems 70/100 == 0
            if i <= ( (allowed_percent/100.0) * len(self) ):
                # if we are currently less than equal to the allow side
                # then select from the allow list
                randlist[i] = Random().choice(self.allowed)
            else:
                randlist[i] = Random().choice(self.disallowed)

        for i in range(0, len(self), 1):
            # get random location in the random list
            randloc = Random().randint(0, len(randlist)-1)
            # extract the value from that spot to fill self
            self[i] = randlist[randloc]
            # delete the location with the value
            del randlist[randloc]


    #def CacheFonts(self, fgcolor, bgcolor):
    #    # cache the fonts for the current
    #    self.cached_fonts = [] # init to empty list (it's recreated to match the size of self)
    #    font = pangofont.PangoFont(family=None, size=text_size)
    #    for i in self:
    #        self.cached_fonts.append( font.render(i,True,fgcolor,bgcolor) )


    def LoadBoardID(self, board_id):
        ''' load some type of board data from the xml given the ID to load'''
        tree = ElementTree(file='XOMuncher-init.xml')
        root = tree.getroot()
        init = tree.findall("init/board")

        for bdata in init:
            for blist in list(bdata):
                if blist.tag == 'level' and blist.text == str(board_id):
                    # load allow and disallow list
                    for bid in bdata.getchildren():
                        if bid.tag == 'level':
                            self.level = bid.text
                        elif bid.tag == 'description':
                            self.description = bid.text
                        elif bid.tag == 'allowed':
                            self.allowed = eval(bid.text)
                        elif bid.tag == 'disallowed':
                            self.disallowed = eval(bid.text)
                    
                    # calculate the max length from allowed list
                    for i in self.allowed:
                        if self.max_text_length < len(str(i)):
                            self.max_text_length = len(str(i))
                    # calculate the max length from disallowed list
                    for i in self.disallowed:
                        if self.max_text_length < len(str(i)):
                            self.max_text_length = len(str(i))
                    
                    break #break out of the blist loop
        

    def GetBoardIDs(self):
        ''' get all the board ID's available in the XML file,
            returns a list of allowed levels
        '''
        tree = ElementTree(file='XOMuncher-init.xml')
        root = tree.getroot()
        level_list = []
        for i in tree.findall("init/board/level"):
            level_list.extend(i.text)
        # return the list
        return level_list


    def GetValue(self, x, y):
        ''' returns the value at x, y '''
        if x < 0 or y < 0 or x >= self.WIDTH or y >= self.HEIGHT:
            raise ValueError, 'Board value out of range'

        # get the value at that x y pos
        #
        # 0 1 2 3
        # 4 5 6 7
        # 8 9 10 11
        return self[ y * self.WIDTH + x ]
        
    def SetValue(self, x, y, value_type):
        ''' set the board position at a given x, y to the value_type '''
        if x < 0 or y < 0 or x >= self.WIDTH or y >= self.HEIGHT:
            raise ValueError, 'Board value out of range'

        # if the value type is anything but VALUE_NONE, then
        # it will be selected randomly from the list
        pos = y * self.WIDTH + x
        if value_type == self.VALUE_NONE:
            self[ pos ] = None
            # not reset cache because if it's None, it should NOT be drawn anyway
        elif value_type == self.VALUE_ALLOWED:
            self[ pos ] = Random().choice(allowed) #for monster to change values
            self.cached_fonts = None # reset because a value changed and it should be redrawn
        elif value_type == self.VALUE_DISALLOWED:
            self[ pos ] = Random().choice(disallowed) #for monster to change values
            self.cached_fonts = None # reset because a value changed and it should be redrawn
        else:
            raise ValueError, 'Invalid Value type specified'
        
    def CheckDone(self):
        ''' returns TRUE if the board is complete ... (no more allowed values on the board '''
        # basically if the board has no more values that intersect with the
        # allowed list, then the board is done
        return (set(self).intersection(set(self.allowed)) == set([]))
        


# load board state
# save board state
